home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / Spiele / GEMSPIEL / COLTRIS / SOURCES / COLTRIS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-17  |  48.0 KB  |  2,123 lines

  1. #include "cltr.h"
  2.  
  3. #include <portab.h>
  4. #include <tos.h>
  5. #include <xgem.h>
  6.  
  7. #include <vaproto.h>
  8.  
  9. #define ICF_GETPOS   0x0001
  10. #define ICF_FREEPOS  0x0002
  11.  
  12. #include "coltris.rh"
  13. #include "coltris.h"
  14.  
  15. extern void (*qcopy)(char *dest,char *source,int lines);
  16. void clr_feld(void);
  17.  
  18. void init_copy_out(void);
  19.  
  20. int ap_id,av_id=-1;            /* für AV/VA-protocoll */
  21. int av_state;
  22.  
  23.                             /* object-bäume */
  24. OBJECT *menue,*options,*info,*user_keys;
  25. OBJECT *score,*stat;
  26. OBJECT *hi_name,*hiscore;
  27. OBJECT *icon;
  28.  
  29. /*
  30.         tastaturkommandos
  31. */
  32. typedef struct {
  33.     int entry;
  34.     int key;
  35.     int state;
  36. } KEY_COMMAND;
  37.  
  38. KEY_COMMAND commands[]={
  39. M_START        ,0x13,    K_CTRL,    /* r */
  40. M_START        ,0x13,    0,        /* r */
  41. M_START        ,0x1c,    0,        /* return */
  42. M_START        ,0x72,    0,        /* enter */
  43. M_HISCORE    ,0x23,    K_CTRL,    /* h */
  44. M_HISCORE    ,0x23,    0,        /* h */
  45. M_ABORT        ,0x10,    K_ALT,    /* q */
  46. M_QUIT        ,0x10,    K_CTRL,    /* q */
  47. M_TETRIS     ,0x14,    K_CTRL,    /* t */
  48. M_TETRIS     ,0x14,    0,        /* t */
  49. M_COLUMNS    ,0x2e,    K_CTRL,    /* c */
  50. M_COLUMNS    ,0x2e,    0,        /* c */
  51. M_SCORE        ,0x17,    K_CTRL,    /* i */
  52. M_SCORE        ,0x17,    0,        /* i */
  53. M_PREVIEW    ,0x31,    K_CTRL,    /* n */
  54. M_PREVIEW    ,0x31,    0,        /* n */
  55. M_STATISTIC    ,0x30,    K_CTRL,    /* b */
  56. M_STATISTIC    ,0x30,    0,        /* b */
  57. M_OPTS        ,0x18,    K_CTRL,    /* o */
  58. M_OPTS        ,0x18,    0,        /* o */
  59. M_STONES    ,0x1F,    K_CTRL,    /* s */
  60. M_STONES    ,0x1F,    0,        /* s */
  61. };
  62.  
  63. char set_file[128]="COLTRIS.SET";
  64.  
  65. OPTS opts={
  66.     PM_TETRIS, 0, 0,0,1,0,0,1,0,0,0,0,0,
  67.     {{"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0},
  68.      {"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0}},
  69.     {{7,0,1,0,0},{7,0,1,0,0}},
  70.     {{{{{240,50},{68,50},{377,50},{148,198}},120,320,0,19,640,381}},
  71.      {{{{240,50},{68,50},{377,50},{148,198}},120,320,0,19,640,381}}},
  72.     {{"TETRIS1.IMG","TETRIS2.IMG","TETRIS4.IMG","TETRIS8.IMG"},
  73.      {"COLUMNS1.IMG","COLUMNS2.IMG","COLUMNS4.IMG","COLUMNS8.IMG"}},
  74. };
  75.  
  76. POSITION *pos[2];
  77.  
  78. int score_flag,preview_flag,stat_flag;
  79. int prev_x,prev_y,prev_w,prev_h;
  80. int in_game=0;
  81. GAME *game;
  82.  
  83. uint last_score;
  84.  
  85. long screen_addr;
  86. long buffer_addr;
  87. long buffer_size;
  88. int buffer_width,buffer_height;        /* width in byte */
  89. int screen_width;                    /* in byte */
  90. int source_width;
  91. int screen_w,screen_h,planes,planes_nr;
  92. int quick_flag;                        /* copy in screen mit ass-routine erlaubt */
  93. int x_off,y_off,width;
  94.  
  95. MFDB screen,buffer;
  96. int handle;                    /* vdi-handle */
  97.  
  98. int do_control(int flag);
  99.  
  100. /*
  101.  
  102.     fenster-routinen
  103.  
  104. */
  105. void redraw_play(int *message);
  106. void close_window(void);
  107. void set_score(void);
  108. void redraw_score(int *message);
  109. void set_preview(void);
  110. void redraw_preview(int *message);
  111. void set_statistic(void);
  112. void redraw_statistic(int *message);
  113.  
  114. #define WIND_ELEMENTS    NAME|MOVER|CLOSER
  115. #define WIND_XELEMENTS    NAME|MOVER|CLOSER|(SMALLER*aes_iconify)
  116.  
  117. WINDOW wind[WIND_ANZ]={-1,redraw_play,close_window,
  118.                        -1,redraw_score,set_score,
  119.                        -1,redraw_preview,set_preview,
  120.                        -1,redraw_statistic,set_statistic};
  121.  
  122. int aes_iconify;
  123. int icon_nr;
  124. int iconified_handle=-1;
  125. int iconified_pos;
  126. int cdecl (*iconify_server)(int opt,...);        /* für iconfy */
  127.  
  128. int check_recs(int x,int y,int w,int h,int *x1,int *y1,int *w1,int *h1)
  129. {
  130. int hx1,hy1,hx2,hy2;
  131.  
  132.     hx2=min(x+w,*x1+*w1);
  133.     hy2=min(y+h,*y1+*h1);
  134.     hx1=max(x,*x1);
  135.     hy1=max(y,*y1);
  136.     *x1=hx1; *y1=hy1;
  137.     *w1=hx2-hx1; *h1=hy2-hy1;
  138.     return( (hx2>hx1)&&(hy2>hy1) );
  139. }
  140.  
  141. /*------------------------------------------------------------------------------
  142.  
  143.     zufallszahlengenerator nach knuth
  144.  
  145. ------------------------------------------------------------------------------*/
  146. #define MBIG    1000000000l
  147. #define MSEED    161803398l
  148. #define FAC    1e-9
  149.  
  150. long xrandom(void)
  151. {
  152. /*    return Random();*/
  153. static int first=0;
  154. static long ma[55],inext,inextp;
  155. long mj,mk;
  156. int i,ii,k;
  157.  
  158.     if ( !first ) {
  159.         first=1;
  160.         mj=MSEED-Random();        /* -> bios zufallszahl für init */
  161.         mj=labs(mj%MBIG);
  162.  
  163.         ma[54]=mj;
  164.         mk=1;
  165.         for ( i=0; i<54; i++ ) {
  166.             ii=(21*i+21)%55-1;
  167.             ma[ii]=mk;
  168.             mk=mj-mk;
  169.             if ( mk<0 )
  170.                 mk+=MBIG;
  171.             mj=ma[ii];
  172.         }
  173.         for ( k=0; k<4; k++ ) {
  174.             for ( i=0; i<55; i++ ) {
  175.                 ma[i]=ma[i]-ma[(i+31)%55];
  176.                 if ( ma[i]<0 )
  177.                     ma[i]+=MBIG;
  178.             }
  179.         }
  180.         inext=-1;
  181.         inextp=30;
  182.     }
  183.  
  184.     inext++;
  185.     if ( inext==55 )
  186.         inext=0;
  187.     inextp++;
  188.     if ( inextp==55 )
  189.         inextp=0;
  190.     mj=ma[inext]-ma[inextp];
  191.     if ( mj<0 )
  192.         mj+=MBIG;
  193.     ma[inext]=mj;
  194.     return mj;
  195. }
  196.  
  197. /*------------------------------------------------------------------------------
  198.  
  199.     timer-routinen
  200.  
  201. ------------------------------------------------------------------------------*/
  202. static long _gettimer(void)
  203. {
  204.     return *(long*)0x4BA;
  205. }
  206. long gettime(void)
  207. {
  208.     return Supexec(_gettimer);
  209. }
  210.  
  211. static long time;
  212. void init_wait(void)
  213. {
  214.     time=gettime();
  215. }
  216. void do_wait(int ms)
  217. {
  218.     if ( !time )
  219.         init_wait();
  220.     while ( gettime()<time+ms )
  221.         ;
  222.     time=0l;
  223. }
  224.  
  225. uint calc_delay(uint level)
  226. {
  227.     return 55-level*5;
  228. }
  229.  
  230. /*
  231.         pause im spiel
  232.  
  233.         *** IMPROVEMENT: hide playfield during pause
  234. */
  235. void do_pause(void)
  236. {
  237. WINDOWS w;
  238. int exit_iconify(void);
  239. int is_iconified(void);
  240.  
  241.     if ( !opts.multi ) {
  242.         wind_update(END_UPDATE);
  243.         wind_update(END_MCTRL);
  244.         v_show_c(handle,1);
  245.     }
  246.     do_control(-1);
  247.     
  248.     if ( is_iconified() )
  249.         exit_iconify();
  250.  
  251.     if ( !opts.multi ) {
  252.         wind_update(BEG_UPDATE);
  253.         wind_update(BEG_MCTRL);
  254.         v_hide_c(handle);
  255.     }
  256.     if ( opts.top ) {
  257.         for ( w=WIND_ANZ-1; w>=0; w-- ) {
  258.             if ( wind[w].handle>=0 ) {
  259.                 wind_set(wind[w].handle,WF_TOP);
  260.                 wind[w].redraw(0l);
  261.             }
  262.         }
  263.     }
  264.     else {
  265.         wind_set(wind[W_PLAY].handle,WF_TOP);
  266.         redraw_play(0l);
  267.     }
  268. }
  269.  
  270. /*------------------------------------------------------------------------------
  271.  
  272.     tastatur-routinen
  273.  
  274. ------------------------------------------------------------------------------*/
  275.  
  276. KEY do_get_key(void)
  277. {
  278. int key;
  279. EVENT evnt;
  280.  
  281.     evnt.ev_mflags=MU_KEYBD|MU_TIMER;
  282.     evnt.ev_mtlocount=1;
  283.     evnt.ev_mthicount=0;
  284.     if ( EvntMulti(&evnt)==MU_TIMER )
  285.         return NO_KEY;
  286.     key=*(char*)&evnt.ev_mkreturn;
  287.  
  288.         /* user-keys first */
  289.     if ( key==opts.left )
  290.         return K_LEFT;
  291.     if ( key==opts.right )
  292.         return K_RIGHT;
  293.     if ( key==opts.rotate )
  294.         return K_ROTATE;
  295.     if ( key==opts.rot_ccw )
  296.         return K_ROT_CCW;
  297.     if ( key==opts.drop )
  298.         return K_DROP;
  299.  
  300.     if ( key==0x67 )                /* 7z */
  301.         return K_LEFT;
  302.     if ( key==0x69 )                /* 9z */
  303.         return K_RIGHT;
  304.     if ( key==0x68 )                /* 8z */
  305.         return K_ROTATE;
  306.     if ( key==0x64 )                /* )z */
  307.         return K_ROT_CCW;
  308.     if ( key==0x39 || key==0x6A )    /* space, 4z */
  309.         return K_DROP;
  310.     if ( key==0x01 || key==0x10 )    /* esc, q */
  311.         return K_QUIT;
  312.     if ( key==0x17 )                /* i */
  313.         return K_INFO;
  314.     if ( key==0x31 )                /* n */
  315.         return K_NEXT;
  316.     if ( key==0x30 )                /* b */
  317.         return K_STAT;
  318.     if ( key==0x1F )                /* s */
  319.         return K_STOP;
  320.     if ( key==0x66 || key==0x26 )    /* *z l */
  321.         return K_LEVEL;
  322.  
  323.     return NO_KEY;
  324. }
  325.  
  326. /*
  327.     gebe taste (funktions-code) zurück (ohne warten)    
  328.  
  329.     bearbeite:
  330.         toggle preview
  331.                info
  332.                statistik
  333.         pause
  334. */
  335. KEY get_key(void)
  336. {
  337. KEY key;
  338.  
  339.     while ( 1 ) {
  340.         key=do_get_key();
  341.         switch ( key ) {
  342.           case K_NEXT:
  343.             set_preview();
  344.             if ( preview_flag )
  345.                 redraw_preview(0l);
  346.             else
  347.                 window_closed();
  348.           break;
  349.           case K_INFO:
  350.               set_score();
  351.             if ( !score_flag )
  352.                 window_closed();
  353.           break;
  354.           case K_STAT:
  355.               set_statistic();
  356.             if ( !stat_flag )
  357.                 window_closed();
  358.           break;
  359.           case K_STOP:
  360.             do_pause();
  361.           break;
  362.           default:
  363.           return key;
  364.         }
  365.     }
  366. }
  367.  
  368. /*
  369.         lösche tastaturpuffer
  370. */
  371. void clr_keys(void)
  372. {
  373. EVENT evnt;
  374.  
  375.     evnt.ev_mflags=MU_KEYBD|MU_TIMER;
  376.     evnt.ev_mtlocount=1;
  377.     evnt.ev_mthicount=0;
  378.     while ( EvntMulti(&evnt)&MU_KEYBD )
  379.         ;
  380. }
  381.  
  382. /*
  383.         hole taste (scancode) mit warten
  384. */
  385. int xget_key(void)
  386. {
  387. int key;
  388.  
  389.     key=evnt_keybd();
  390.     return *(char*)&key;
  391. }
  392.  
  393. void window_closed(void)
  394. {
  395. int top,d;
  396.  
  397.     if ( !opts.multi ) {
  398.         wind_update(END_UPDATE);
  399.         wind_update(END_MCTRL);
  400.         v_show_c(handle,1);
  401.     }
  402.     do_control(100);
  403.     if ( !opts.multi ) {
  404.         wind_update(BEG_UPDATE);
  405.         wind_update(BEG_MCTRL);
  406.         v_hide_c(handle);
  407.     }
  408.     wind_get(0,WF_TOP,&top,&d,&d,&d);
  409.     if ( d!=wind[W_PLAY].handle ) {
  410.         wind_set(wind[W_PLAY].handle,WF_TOP);
  411.         redraw_play(0l);
  412.     }
  413. }
  414.  
  415. /*------------------------------------------------------------------------------
  416.  
  417.     hiscore
  418.  
  419. ------------------------------------------------------------------------------*/
  420. void do_score(uint score,HI_SCORE *hi)
  421. {
  422. int i,j;
  423. int x,y,w,h;
  424.  
  425.     last_score=score;
  426.  
  427.     for ( i=0; i<10; i++ ) {
  428.         if ( score>hi[i].score ) {
  429. #if SOUND_LEVEL>0
  430.             do_sound(S_HISCORE);
  431. #endif
  432.             wind_update(BEG_UPDATE);
  433.             form_center(hi_name,&x,&y,&w,&h);
  434.             form_dial(FMD_START,x,y,w,h,x,y,w,h);
  435.             objc_draw(hi_name,0,10,x,y,w,h);
  436.             form_do(hi_name,HI_NAME);
  437.             form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  438.             wind_update(END_UPDATE);
  439.  
  440.             obj_unselect(hi_name,HI_NAME);
  441.             for ( j=9; j>i; j-- )
  442.                 hi[j]=hi[j-1];
  443.             strcpy(hi[i].name,obj_tedstr(hi_name,HI_NAME));
  444.             hi[i].score=score;
  445.             hi[i].date=Tgetdate();
  446.             return;
  447.         }
  448.     }
  449. #if SOUND_LEVEL>0
  450.     if ( i==10 )
  451.         do_sound(S_NOHISCORE);
  452. #endif
  453. }
  454.  
  455. void show_hiscore(void)
  456. {
  457. HI_SCORE *hi;
  458. int i,ret,x,y,w,h;
  459. uint date;
  460. char title[32];
  461.  
  462.     sprintf(title,"%s Hiscore",game->name);
  463.     obj_spec(hiscore,HI_TITEL)=title;
  464.  
  465.     hi=opts.hiscore[opts.play_mode];
  466.  
  467.     obj_hide(hiscore,HI_MARKE);
  468.     for ( i=0; i<10; i++ ) {
  469.         if ( hi[i].score!=0 ) {
  470.             strcpy(obj_spec(hiscore,HISCORE1+i+i+i),hi[i].name);
  471.             date=hi[i].date;
  472.             sprintf(obj_spec(hiscore,HISCORE1+1+i+i+i),"%2d.%2d.%4d",date&31,(date>>5)&15,(date>>9)+1980);
  473.             sprintf(obj_spec(hiscore,HISCORE1+2+i+i+i),"%5d",hi[i].score);
  474.             if ( hi[i].score==last_score ) {
  475.                 obj_unhide(hiscore,HI_MARKE);
  476.                 hiscore[HI_MARKE].ob_y=hiscore[HISCORE1+i+i+i].ob_y;
  477.             }
  478.         }
  479.         else {
  480.             *obj_spec(hiscore,HISCORE1+i+i+i)=0;
  481.             *obj_spec(hiscore,HISCORE1+1+i+i+i)=0;
  482.             *obj_spec(hiscore,HISCORE1+2+i+i+i)=0;
  483.         }
  484.  
  485.     }
  486.  
  487.     form_center(hiscore,&x,&y,&w,&h);
  488.     wind_update(BEG_UPDATE);
  489.     form_dial(FMD_START,x,y,w,h,x,y,w,h);
  490.     objc_draw(hiscore,0,10,x,y,w,h);
  491.     ret=form_do(hiscore,0)&0x7FFF;
  492.     obj_unselect(hiscore,ret);
  493.     form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  494.     wind_update(END_UPDATE);
  495.     if ( ret==CLR_HI ) {
  496.         for ( i=0; i<10; i++ ) {
  497.             strcpy(hi[i].name,"");
  498.             hi[i].score=0;
  499.             hi[i].date=0;
  500.         }
  501.     }
  502. }
  503.  
  504. /*------------------------------------------------------------------------------
  505.  
  506.     schreibe optionen in / lese optionen aus  dialogbox
  507.  
  508. ------------------------------------------------------------------------------*/
  509. void set_opts(void)
  510. {
  511. GAME_OPTS *go;
  512. int i;
  513.  
  514.     go=&opts.opts[opts.play_mode];
  515.     if ( opts.play_mode==PM_COLUMNS ) {
  516.         obj_select(options,O_COLUMNS);
  517.         obj_unselect(options,O_TETRIS);
  518.     }
  519.     else {
  520.         obj_select(options,O_TETRIS);
  521.         obj_unselect(options,O_COLUMNS);
  522.     }
  523.     for ( i=LEVEL0; i<=LEVEL9; i++ ) {
  524.         obj_unselect(options,i);
  525.     }
  526.     if ( go->start_level<9 )
  527.         obj_select(options,LEVEL0+go->start_level);
  528.  
  529.     for ( i=RANDOM0; i<=RANDOM14; i++ ) {
  530.         obj_unselect(options,i);
  531.     }
  532.     if ( go->random<14 )
  533.         obj_select(options,RANDOM0+go->random);
  534.  
  535.     obj_unselect(options,SOUND_ON);
  536.     obj_unselect(options,SOUND_OFF);
  537.     if ( opts.sound )
  538.         obj_select(options,SOUND_ON);
  539.     else
  540.         obj_select(options,SOUND_OFF);
  541.  
  542.     obj_unselect(options,GRAPH_ST);
  543.     obj_unselect(options,GRAPH_VDI);
  544.     if ( columns.vdi )
  545.         obj_disable(options,O_GCOL);
  546.     else
  547.         obj_enable(options,O_GCOL);
  548.     if ( tetris.vdi )
  549.         obj_disable(options,O_GTET);
  550.     else
  551.         obj_enable(options,O_GTET);
  552.     if ( columns.vdi && tetris.vdi ) {
  553.         obj_disable(options,GRAPH_ST);
  554.         obj_disable(options,GRAPH_VDI);
  555.     }
  556.     else {
  557.         obj_enable(options,GRAPH_ST);
  558.         obj_enable(options,GRAPH_VDI);
  559.         if ( opts.graph )
  560.             obj_select(options,GRAPH_VDI);
  561.         else
  562.             obj_select(options,GRAPH_ST);
  563.     }
  564.  
  565.     obj_unselect(options,SINGLE);
  566.     obj_unselect(options,MULTI);
  567.     if ( opts.multi )
  568.         obj_select(options,MULTI);
  569.     else
  570.         obj_select(options,SINGLE);
  571.  
  572.     obj_unselect(options,CYCLENONE);
  573.     obj_unselect(options,CYCLEPLAY);
  574.     obj_unselect(options,CYCLEALL);
  575.     if ( opts.cycle==0 )
  576.         obj_select(options,CYCLENONE);
  577.     else if ( opts.cycle==1 )
  578.         obj_select(options,CYCLEPLAY);
  579.     else
  580.         obj_select(options,CYCLEALL);
  581.  
  582.     if ( opts.top )
  583.         obj_select(options,TOP_ALL);
  584.     else
  585.         obj_unselect(options,TOP_ALL);
  586.  
  587.     if ( opts.alert )
  588.         obj_select(options,ALERT);
  589.     else
  590.         obj_unselect(options,ALERT);
  591. }
  592.  
  593. void get_opts(void)
  594. {
  595. GAME_OPTS *go;
  596. int i;
  597.  
  598.     go=&opts.opts[opts.play_mode];
  599.  
  600.     for ( i=LEVEL0; i<=LEVEL9; i++ ) {
  601.         if ( obj_selected(options,i) )
  602.             { go->start_level=i-LEVEL0; break; }
  603.     }
  604.  
  605.     for ( i=RANDOM0; i<=RANDOM14; i++ ) {
  606.         if ( obj_selected(options,i) )
  607.             { go->random=i-RANDOM0; break; }
  608.     }
  609.  
  610.     if ( obj_selected(options,SOUND_ON) )
  611.         opts.sound=1;
  612.     else
  613.         opts.sound=0;
  614.  
  615.     if ( obj_selected(options,GRAPH_VDI) )
  616.         opts.graph=1;
  617.     else if ( obj_selected(options,GRAPH_ST) )    /* possibly none selected */
  618.         opts.graph=0;
  619.  
  620.     if ( obj_selected(options,MULTI) )
  621.         opts.multi=1;
  622.     else
  623.         opts.multi=0;
  624.  
  625.     if ( obj_selected(options,CYCLENONE) )
  626.         opts.cycle=0;
  627.     else if ( obj_selected(options,CYCLEPLAY) )
  628.         opts.cycle=1;
  629.     else
  630.         opts.cycle=2;
  631.  
  632.     if ( obj_selected(options,TOP_ALL) )
  633.         opts.top=1;
  634.     else
  635.         opts.top=0;
  636.  
  637.     if ( obj_selected(options,ALERT) )
  638.         opts.alert=1;
  639.     else
  640.         opts.alert=0;
  641. }
  642.  
  643. void get_user_keys(void)
  644. {
  645. int x,y,w,h;
  646.  
  647.     wind_update(BEG_MCTRL);
  648.     wind_update(BEG_UPDATE);
  649.  
  650.     strcpy(obj_spec(user_keys,KEYS_TXT),"Left");
  651.     form_center(user_keys,&x,&y,&w,&h);
  652.     objc_draw(user_keys,0,10,x,y,w,h);
  653.     opts.left=xget_key();
  654.  
  655.     strcpy(obj_spec(user_keys,KEYS_TXT),"Right");
  656.     form_center(user_keys,&x,&y,&w,&h);
  657.     objc_draw(user_keys,0,10,x,y,w,h);
  658.     opts.right=xget_key();
  659.  
  660.     strcpy(obj_spec(user_keys,KEYS_TXT),"Rotate");
  661.     form_center(user_keys,&x,&y,&w,&h);
  662.     objc_draw(user_keys,0,10,x,y,w,h);
  663.     opts.rotate=xget_key();
  664.  
  665.     strcpy(obj_spec(user_keys,KEYS_TXT),"Rotate ccw");
  666.     form_center(user_keys,&x,&y,&w,&h);
  667.     objc_draw(user_keys,0,10,x,y,w,h);
  668.     opts.rot_ccw=xget_key();
  669.  
  670.     strcpy(obj_spec(user_keys,KEYS_TXT),"Drop");
  671.     form_center(user_keys,&x,&y,&w,&h);
  672.     objc_draw(user_keys,0,10,x,y,w,h);
  673.     opts.drop=xget_key();
  674.  
  675.     wind_update(END_MCTRL);
  676.     wind_update(END_UPDATE);
  677. }
  678.  
  679. void do_options(void)
  680. {
  681. int x,y,w,h,r;
  682.  
  683.     wind_update(BEG_UPDATE);
  684.     form_center(options,&x,&y,&w,&h);
  685.     form_dial(FMD_START,x,y,w,h,x,y,w,h);
  686.  
  687.     set_opts();
  688.  
  689.     do {
  690.         objc_draw(options,0,10,x,y,w,h);
  691.         r=form_do(options,0)&0x7FFF;
  692.         obj_unselect(options,r);
  693.         if ( r==USER_KEY ) {
  694.             get_user_keys();
  695.         }
  696.     } while ( r!=OK && r!=ABBR );
  697.  
  698.     if ( r==OK ) {
  699.         get_opts();
  700.         init_copy_out();
  701.     }
  702.  
  703.     form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  704.     wind_update(END_UPDATE);
  705. }
  706.  
  707. void save_options(void)
  708. {
  709. int f_id;
  710.  
  711.     f_id=Fcreate(set_file,0);
  712.     if ( f_id>0 ) {
  713.         Fwrite(f_id,sizeof(opts),&opts);
  714.         Fclose(f_id);
  715.     }
  716. }
  717.  
  718. /*------------------------------------------------------------------------------
  719.  
  720.     sende für av_protokol
  721.  
  722. ------------------------------------------------------------------------------*/
  723. char *get_send_puffer(void)
  724. {
  725. static char *send_puffer=0l;
  726.  
  727.     if ( !send_puffer ) {
  728.         send_puffer=Mxalloc(256,0x0022);
  729.         if ( send_puffer==(char*)-32 )
  730.             send_puffer=Malloc(256);
  731.     }
  732.     return send_puffer;
  733. }
  734.  
  735. int av_send(int msg_typ,int d1,int d2,char *str1,int s2,char *str2)
  736. {
  737. int msg[8];
  738. char *puf;
  739.  
  740.     if ( av_id<0 || (msg_typ==AV_SENDKEY && !(av_state&1)) ||
  741.          ((msg_typ==AV_ACCWINDOPEN || msg_typ==AV_ACCWINDCLOSED) && !(av_state&64)) ||
  742.          (msg_typ==AV_EXIT && !(av_state&1024))
  743.         )    return 0;
  744.  
  745.     if ( str1 || str2 ) {
  746.         puf=get_send_puffer();
  747.         if ( !puf )
  748.             return 0;
  749.         if ( str1 )
  750.             strcpy(puf,str1);
  751.         if ( str2 )
  752.             strcpy(puf+128,str2);
  753.     }
  754.  
  755.     msg[0]=msg_typ;
  756.     msg[1]=ap_id;
  757.     msg[2]=0;
  758.     msg[3]=msg[4]=msg[5]=msg[6]=msg[7]=0;
  759.  
  760.     if ( str1 ) {
  761.         *(char**)&msg[3]=puf;
  762.     }
  763.     else {
  764.         msg[3]=d1;
  765.         msg[4]=d2;
  766.     }
  767.     if ( str2 ) {
  768.         if ( s2!=5 && s2!=6 )
  769.             s2=5;
  770.         *(char**)&msg[s2]=puf+128;
  771.     }
  772.     appl_write(av_id,16,msg);
  773.     return 1;
  774. }
  775.  
  776. void av_init(void)
  777. {
  778. char *av,_av[32];
  779.  
  780.         /* av/va kommunikationspartner einstellen */
  781.     av=getenv("AVSERVER");
  782.     if ( av!=0l ) {
  783.         strncpy(_av,av,16);
  784.         _av[16]=0;
  785.         strcat(_av,"        ");
  786.         _av[8]=0;
  787.         av_id=appl_find(_av);
  788.     }
  789.     av_send(AV_PROTOKOLL,2,0,0l,6,"COLTRIS ");
  790. }
  791.  
  792. void av_getproto(void)
  793. {
  794. int evnt;
  795. EVENT event;
  796.  
  797.     do {
  798.         memset(&event,0,sizeof(event));
  799.         event.ev_mflags=MU_MESAG|MU_TIMER;
  800.         event.ev_mtlocount=10;
  801.         /*event.ev_mthicount=0;*/
  802.         evnt=EvntMulti(&event);
  803.         if ( evnt&MU_MESAG && event.ev_mmgpbuf[0]==VA_PROTOSTATUS )
  804.             av_state=event.ev_mmgpbuf[3];
  805.     } while ( evnt&MU_MESAG );
  806. }
  807.  
  808. /*------------------------------------------------------------------------------
  809.  
  810.     init play-window...
  811.  
  812. ------------------------------------------------------------------------------*/
  813. void init_buffer(int width,int height)
  814. {
  815. int xwidth;
  816.  
  817.     if ( buffer_addr )
  818.         free((void*)buffer_addr);
  819.  
  820.     xwidth=(width+15)&~15;
  821.  
  822.     buffer_size=(long)xwidth*(long)height*(long)planes/8l;
  823.     buffer_addr=(long)malloc(buffer_size);
  824.     if ( !buffer_addr )
  825.         exit(1);
  826.     memset((void*)buffer_addr,0,buffer_size);
  827.     buffer.fd_addr=(void*)buffer_addr;
  828.     buffer.fd_w=xwidth;
  829.     buffer.fd_h=height;
  830.     buffer.fd_wdwidth=xwidth/16;
  831.     buffer.fd_nplanes=planes;
  832.     buffer.fd_stand=0;
  833.     buffer.fd_r1=buffer.fd_r2=buffer.fd_r3=0;
  834.  
  835.     buffer_width=xwidth/8;
  836.     buffer_height=height;
  837.  
  838. }
  839.  
  840. void check_windpos(int *x,int *y)
  841. {
  842.     if ( *x<pos[0]->desk_x )
  843.         *x=pos[0]->desk_x;
  844.     else if ( *x>pos[0]->desk_x+pos[0]->desk_w-32 )
  845.         *x=pos[0]->desk_x+pos[0]->desk_w-32;
  846.     if ( *y<pos[0]->desk_y )
  847.         *y=pos[0]->desk_y;
  848.     else if ( *y>pos[0]->desk_y+pos[0]->desk_h-32 )
  849.         *y=pos[0]->desk_y+pos[0]->desk_h-32;
  850. }
  851.  
  852. void init_window(int *x_x,int *y_y,int *w_w,int *h_h)
  853. {
  854. int x,y,w,h,xx,yy,ww,hh;
  855. int height;
  856.  
  857.     width=game->block_w*game->game_width;
  858.     height=game->block_h*game->game_height;
  859.  
  860.     wind_calc(WC_BORDER,WIND_XELEMENTS,pos[opts.play_mode]->wind_pos[W_PLAY].x,pos[opts.play_mode]->wind_pos[W_PLAY].y,width,height,&x,&y,&w,&h);
  861.     check_windpos(&x,&y);
  862.     wind_calc(WC_WORK,WIND_XELEMENTS,x,y,w,h,&xx,&yy,&ww,&hh);
  863.     xx&=~15;
  864.     wind_calc(WC_BORDER,WIND_XELEMENTS,xx,yy,ww,hh,&x,&y,&w,&h);
  865.     *x_x=x;
  866.     *y_y=y;
  867.     *w_w=w;
  868.     *h_h=h;
  869.  
  870.     init_buffer(width,height);
  871.     source_width=game->source_width*2;    /* game->source_width ist breite für block in pixel
  872.                                             -> *16 (bloecke) / 8 für byte */
  873.  
  874.     init_copy_out();
  875. }
  876.  
  877. int open_window(void)
  878. {
  879. int x,y,w,h,dummy;
  880.  
  881.     wind[W_PLAY].handle=wind_create(WIND_XELEMENTS,0,0,screen_w,screen_h);
  882.     if ( wind[W_PLAY].handle<0 )
  883.         return 0;
  884.     init_window(&x,&y,&w,&h);
  885.     if ( opts.play_mode==PM_COLUMNS )
  886.         wind_set(wind[W_PLAY].handle,WF_NAME," Columns ");
  887.     else
  888.         wind_set(wind[W_PLAY].handle,WF_NAME," Tetris ");
  889.     wind_open(wind[W_PLAY].handle,x,y,w,h);
  890.     if ( opts.cycle )
  891.         av_send(AV_ACCWINDOPEN,wind[W_PLAY].handle,0,0l,0,0l);
  892.     wind_get(wind[W_PLAY].handle,WF_WORKXYWH,&pos[opts.play_mode]->wind_pos[W_PLAY].x,&pos[opts.play_mode]->wind_pos[W_PLAY].y,&dummy,&dummy);
  893.     return 1;
  894. }
  895.  
  896.  
  897. void close_window(void)
  898. {
  899.     wind_close(wind[W_PLAY].handle);
  900.     wind_delete(wind[W_PLAY].handle);
  901.     av_send(AV_ACCWINDCLOSED,wind[W_PLAY].handle,0,0l,0,0l);
  902.     wind[W_PLAY].handle=-1;
  903. }
  904.  
  905. int reopen_window(void)
  906. {
  907.      if ( wind[W_STATISTIC].handle!=-1 )
  908.         redraw_statistic(0l);
  909.     close_window();
  910.     return open_window();
  911. }
  912.  
  913. #define ABSTAND    24
  914. void xhide(int *hide,int x,int y,int w,int h)
  915. {
  916. int mx,my,dummy;
  917.  
  918.     if ( *hide )
  919.         return;        /* maus ist hidden */
  920.     graf_mkstate(&mx,&my,&dummy,&dummy);
  921.     if ( mx>x-ABSTAND && mx<=x+w+ABSTAND && my>y-ABSTAND && my<=y+h+ABSTAND ) {
  922.         *hide=1;
  923.         v_hide_c(handle);
  924.     }
  925. }
  926.  
  927. void _redraw_icon(int window_handle,int *clip,OBJECT *icon_tree,int icon_nr)
  928. {
  929. int x,y,w,h;
  930.  
  931.     wind_get(window_handle,WF_WORKXYWH,&x,&y,&w,&h);
  932.     icon_tree->ob_x=x;
  933.     icon_tree->ob_y=y;
  934.     icon_tree[icon_nr].ob_x=(w-icon_tree[icon_nr].ob_width)/2;
  935.     icon_tree[icon_nr].ob_y=(h-icon_tree[icon_nr].ob_height)/2;
  936.  
  937.     wind_get(window_handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  938.     while ( w!=0 ) {
  939.         if ( check_recs(clip[0],clip[1],clip[2],clip[3],&x,&y,&w,&h) )
  940.             objc_draw(icon_tree,0,MAX_DEPTH,x,y,w,h);
  941.         wind_get(window_handle,WF_NEXTXYWH,&x,&y,&w,&h);
  942.     }
  943. }
  944.  
  945. void redraw_play(int *message)
  946. {
  947. int m[8];
  948. int xy[8];
  949. int x,y,w,h,_w;
  950. int xo,yo,ww,hh;
  951. int hide=0;
  952. int iconified,dummy;
  953.  
  954.     if ( !message ) {
  955.         m[3]=wind[W_PLAY].handle;
  956.         m[4]=m[5]=0;
  957.         m[6]=screen_w;
  958.         m[7]=screen_h;
  959.         message=m;
  960.     }
  961.  
  962.     wind_update(BEG_UPDATE);
  963.  
  964.     if ( aes_iconify )
  965.         my_wind_get(message[3],WF_ICONIFY,&iconified,&w,&h,&dummy);
  966.     else
  967.         iconified=0;
  968.  
  969.     if ( iconified ) {
  970.         _redraw_icon(message[3],message+4,icon,icon_nr);
  971.     }
  972.     else {
  973.         wind_get(message[3],WF_WORKXYWH,&xo,&yo,&ww,&hh);
  974.         check_recs(0,0,screen_w,screen_h,&xo,&yo,&ww,&hh);
  975.         wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  976.         while ( w!=0 ) {
  977.             _w=w;
  978.             if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  979.                 if ( _w==ww && quick_flag ) {
  980.                   char *source,*dest;
  981.                     xhide(&hide,xo,y,_w,h);
  982.                     source=(char*)buffer_addr+(long)(y-yo)*buffer_width;
  983.                     dest=(char*)screen_addr+(long)y*screen_width+xo/8;
  984.                     qcopy(dest,source,h-1);
  985.                 }
  986.                 else {
  987.                     xhide(&hide,x,y,w,h);
  988.                     xy[0]=x-xo;
  989.                     xy[1]=y-yo;
  990.                     xy[2]=x-xo+w-1;
  991.                     xy[3]=y-yo+h-1;
  992.                     xy[4]=x;
  993.                     xy[5]=y;
  994.                     xy[6]=x+w-1;
  995.                     xy[7]=y+h-1;
  996.                     vro_cpyfm(handle,S_ONLY,xy,&buffer,&screen);
  997.                 }
  998.             }
  999.             wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1000.         }
  1001.         if ( hide )
  1002.             v_show_c(handle,1);
  1003.     }
  1004.     wind_update(END_UPDATE);
  1005. }
  1006.  
  1007. void do_endgame(void)
  1008. {
  1009. }
  1010.  
  1011. void set_wind_pos(int handle,WIND_POS *pos)
  1012. {
  1013. int dummy,x,y,w,h;
  1014.  
  1015.     wind_get(handle,WF_WORKXYWH,&dummy,&dummy,&w,&h);
  1016.     wind_calc(WC_BORDER,WIND_ELEMENTS,pos->x,pos->y,w,h,&x,&y,&w,&h);
  1017.     check_windpos(&x,&y);
  1018.     wind_set(handle,WF_CURRXYWH,x,y,w,h);
  1019. }
  1020.  
  1021. void set_playmode(PLAY_MODE pm)
  1022. {
  1023. int x,y,w,h;
  1024. GAME_OPTS *go;
  1025.  
  1026.     if ( opts.play_mode==pm )
  1027.         return;
  1028.  
  1029.     opts.play_mode=pm;
  1030.     if ( pm==PM_TETRIS ) {
  1031.         menu_icheck(menue,M_TETRIS,1);
  1032.         menu_icheck(menue,M_COLUMNS,0);
  1033.         obj_hide(stat,C_STAT);
  1034.         obj_unhide(stat,TSTAT);
  1035.         wind_set(wind[W_PLAY].handle,WF_NAME," Tetris ");
  1036.         game=&tetris;
  1037.     }
  1038.     else {
  1039.         menu_icheck(menue,M_TETRIS,0);
  1040.         menu_icheck(menue,M_COLUMNS,1);
  1041.         obj_unhide(stat,C_STAT);
  1042.         obj_hide(stat,TSTAT);
  1043.         wind_set(wind[W_PLAY].handle,WF_NAME," Columns ");
  1044.         game=&columns;
  1045.     }
  1046.     go=&opts.opts[opts.play_mode];
  1047.  
  1048.     init_window(&x,&y,&w,&h);
  1049.     wind_set(wind[W_PLAY].handle,WF_CURRXYWH,x,y,w,h);
  1050.     clr_feld();
  1051.     if ( go->score!=score_flag )
  1052.         set_score();
  1053.     else if ( score_flag )
  1054.         set_wind_pos(wind[W_SCORE].handle,&pos[pm]->wind_pos[W_SCORE]);
  1055.  
  1056.     if ( go->preview!=preview_flag )
  1057.         set_preview();
  1058.     else if ( preview_flag )
  1059.         set_wind_pos(wind[W_PREVIEW].handle,&pos[pm]->wind_pos[W_PREVIEW]);
  1060.     if ( go->statistic!=stat_flag )
  1061.         set_statistic();
  1062.     else if ( stat_flag ) {
  1063.         set_wind_pos(wind[W_STATISTIC].handle,&pos[pm]->wind_pos[W_STATISTIC]);
  1064.         redraw_statistic(0l);
  1065.     }
  1066. }
  1067.  
  1068. static uint xlevel,xlines,xstones,xscore;
  1069.  
  1070. void dr_score(uint level,uint lines,uint stones,uint sc)
  1071. {
  1072. static int _level=-1,_lines=-1;
  1073. int le,li;
  1074. int x,y,w,h;
  1075. int hide=0;
  1076.  
  1077.     xlevel=level;
  1078.     xlines=lines;
  1079.     xstones=stones;
  1080.     xscore=sc;
  1081.  
  1082.     if ( !score_flag )
  1083.         return;
  1084.  
  1085.     le=li=0;
  1086.     if ( _level!=level ) {
  1087.         _level=level;
  1088.         sprintf(obj_tedstr(score,LEVEL),"%d",level);
  1089.         le=1;
  1090.     }
  1091.     if ( _lines!=lines ) {
  1092.         _lines=lines;
  1093.         sprintf(obj_tedstr(score,LINES),"%5d",lines);
  1094.         li=1;
  1095.     }
  1096.     sprintf(obj_tedstr(score,STONES),"%5d",stones);
  1097.     sprintf(obj_tedstr(score,SCORE),"%5d",sc);
  1098.  
  1099.     wind_get(wind[W_SCORE].handle,WF_WORKXYWH,&x,&y,&w,&h);
  1100.     score->ob_x=x;
  1101.     score->ob_y=y;
  1102.  
  1103.     wind_update(BEG_UPDATE);
  1104.     wind_get(wind[W_SCORE].handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  1105.     while ( w ) {
  1106.         xhide(&hide,x,y,w,h);
  1107.         if ( le )
  1108.             objc_draw(score,LEVEL,0,x,y,w,h);
  1109.         if ( li )
  1110.             objc_draw(score,LINES,0,x,y,w,h);
  1111.         objc_draw(score,STONES,0,x,y,w,h);
  1112.         objc_draw(score,SCORE,0,x,y,w,h);
  1113.         wind_get(wind[W_SCORE].handle,WF_NEXTXYWH,&x,&y,&w,&h);
  1114.     }
  1115.     if ( hide )
  1116.         v_show_c(handle,1);
  1117.     wind_update(END_UPDATE);
  1118. }
  1119.  
  1120. void redraw_score(int *message)
  1121. {
  1122. int m[8];
  1123. int dummy;
  1124. int x,y,w,h;
  1125. int hide=0;
  1126.  
  1127.     if ( !message ) {
  1128.         m[3]=wind[W_SCORE].handle;
  1129.         m[4]=m[5]=0;
  1130.         m[6]=screen_w;
  1131.         m[7]=screen_h;
  1132.         message=m;
  1133.     }
  1134.  
  1135.     wind_get(wind[W_SCORE].handle,WF_WORKXYWH,&x,&y,&dummy,&dummy);
  1136.     score->ob_x=x;
  1137.     score->ob_y=y;
  1138.  
  1139.     wind_update(BEG_UPDATE);
  1140.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  1141.     while ( w!=0 ) {
  1142.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  1143.             xhide(&hide,x,y,w,h);
  1144.             objc_draw(score,0,MAX_DEPTH,x,y,w,h);
  1145.         }
  1146.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1147.     }
  1148.     if ( hide )
  1149.         v_show_c(handle,1);
  1150.     wind_update(END_UPDATE);
  1151. }
  1152.  
  1153. int open_score(void)
  1154. {
  1155. int x,y,w,h,dummy;
  1156.  
  1157.     wind[W_SCORE].handle=wind_create(WIND_ELEMENTS,0,0,screen_w,screen_h);
  1158.     if ( wind[W_SCORE].handle<0 )
  1159.         return 0;
  1160.     wind_calc(WC_BORDER,WIND_ELEMENTS,
  1161.         pos[opts.play_mode]->wind_pos[W_SCORE].x,
  1162.         pos[opts.play_mode]->wind_pos[W_SCORE].y,
  1163.         score->ob_width,score->ob_height,&x,&y,&w,&h);
  1164.     check_windpos(&x,&y);
  1165.     wind_set(wind[W_SCORE].handle,WF_NAME," Score ");
  1166.     dr_score(xlevel,xlines,xstones,xscore);
  1167.     wind_open(wind[W_SCORE].handle,x,y,w,h);
  1168.     if ( opts.cycle==2 )
  1169.         av_send(AV_ACCWINDOPEN,wind[W_SCORE].handle,0,0l,0,0l);
  1170.     wind_get(wind[W_SCORE].handle,WF_WORKXYWH,&pos[opts.play_mode]->wind_pos[W_SCORE].x,&pos[opts.play_mode]->wind_pos[W_SCORE].y,&dummy,&dummy);
  1171.     redraw_score(0l);
  1172.     if ( wind[W_PLAY].handle>=0 ) {
  1173.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1174.         redraw_play(0l);
  1175.     }
  1176.     return 1;
  1177. }
  1178.  
  1179.  
  1180. void set_score(void)
  1181. {
  1182.     if ( score_flag ) {
  1183.         wind_close(wind[W_SCORE].handle);
  1184.         wind_delete(wind[W_SCORE].handle);
  1185.         av_send(AV_ACCWINDCLOSED,wind[W_SCORE].handle,0,0l,0,0l);
  1186.         wind[W_SCORE].handle=-1;
  1187.     }
  1188.     else {
  1189.         if ( !open_score() )
  1190.             return;
  1191.     }
  1192.     score_flag=1-score_flag;
  1193.     opts.opts[opts.play_mode].score=score_flag;
  1194.     menu_icheck(menue,M_SCORE,score_flag);
  1195. }
  1196.  
  1197. void redraw_preview(int *message)
  1198. {
  1199. int xy[4];
  1200. int m[8];
  1201. int x,y,w,h;
  1202. int hide=0;
  1203.  
  1204.     if ( !message ) {
  1205.         m[3]=wind[W_PREVIEW].handle;
  1206.         m[4]=m[5]=0;
  1207.         m[6]=screen_w;
  1208.         m[7]=screen_h;
  1209.         message=m;
  1210.     }
  1211.  
  1212.     vsf_style(handle,8);
  1213.     vsf_color(handle,0);
  1214.  
  1215.     wind_update(BEG_UPDATE);
  1216.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  1217.     while ( w!=0 ) {
  1218.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  1219.             xhide(&hide,x,y,w,h);
  1220.             xy[0]=x;
  1221.             xy[1]=y;
  1222.             xy[2]=x+w-1;
  1223.             xy[3]=y+h-1;
  1224.             vs_clip(handle,1,xy);
  1225.             v_bar(handle,xy);
  1226.             if ( in_game ) {
  1227.                 game->preview();
  1228.             }
  1229.         }
  1230.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1231.     }
  1232.     vs_clip(handle,0,xy);
  1233.     if ( hide )
  1234.         v_show_c(handle,1);
  1235.     wind_update(END_UPDATE);
  1236. }
  1237.  
  1238. int open_preview(void)
  1239. {
  1240. int x,y,w,h;
  1241. int cw,ch,tw,th,width,height;
  1242.  
  1243.     cw=columns.prev_width*columns.block_w;
  1244.     ch=columns.prev_height*columns.block_h;
  1245.     tw=tetris.prev_width*tetris.block_w;
  1246.     th=tetris.prev_height*tetris.block_h;
  1247.  
  1248.     width=max(cw,tw);
  1249.     height=max(ch,th);
  1250.  
  1251.     wind[W_PREVIEW].handle=wind_create(WIND_ELEMENTS,0,0,screen_w,screen_h);
  1252.     if ( wind[W_PREVIEW].handle<0 )
  1253.         return 0;
  1254.     wind_calc(WC_BORDER,WIND_ELEMENTS,pos[opts.play_mode]->wind_pos[W_PREVIEW].x,pos[opts.play_mode]->wind_pos[W_PREVIEW].y,width,height,&x,&y,&w,&h);
  1255.     check_windpos(&x,&y);
  1256.     wind_set(wind[W_PREVIEW].handle,WF_NAME," Next ");
  1257.     wind_open(wind[W_PREVIEW].handle,x,y,w,h);
  1258.     if ( opts.cycle==2 )
  1259.         av_send(AV_ACCWINDOPEN,wind[W_PREVIEW].handle,0,0l,0,0l);
  1260.     wind_get(wind[W_PREVIEW].handle,WF_WORKXYWH,&prev_x,&prev_y,&prev_w,&prev_h);
  1261.     pos[opts.play_mode]->wind_pos[W_PREVIEW].x=prev_x;
  1262.     pos[opts.play_mode]->wind_pos[W_PREVIEW].y=prev_y;
  1263.     redraw_preview(0l);
  1264.     if ( wind[W_PLAY].handle>=0 ) {
  1265.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1266.         redraw_play(0l);
  1267.     }
  1268.     return 1;
  1269. }
  1270.  
  1271. void set_preview(void)
  1272. {
  1273.     if ( preview_flag ) {
  1274.         wind_close(wind[W_PREVIEW].handle);
  1275.         wind_delete(wind[W_PREVIEW].handle);
  1276.         av_send(AV_ACCWINDCLOSED,wind[W_PREVIEW].handle,0,0l,0,0l);
  1277.         wind[W_PREVIEW].handle=-1;
  1278.     }
  1279.     else {
  1280.         if ( !open_preview() )
  1281.             return;
  1282.     }
  1283.     preview_flag=1-preview_flag;
  1284.     opts.opts[opts.play_mode].preview=preview_flag;
  1285.     menu_icheck(menue,M_PREVIEW,preview_flag);
  1286. }
  1287.  
  1288. void redraw_statistic(int *message)
  1289. {
  1290. int m[8];
  1291. int dummy;
  1292. int x,y,w,h,xy[4];
  1293. int st_x,st_y,st_dy;
  1294. int hide=0;
  1295.  
  1296.     if ( !message ) {
  1297.         m[3]=wind[W_STATISTIC].handle;
  1298.         m[4]=m[5]=0;
  1299.         m[6]=screen_w;
  1300.         m[7]=screen_h;
  1301.         message=m;
  1302.     }
  1303.  
  1304.     wind_get(wind[W_STATISTIC].handle,WF_WORKXYWH,&x,&y,&dummy,&dummy);
  1305.     stat->ob_x=x;
  1306.     stat->ob_y=y;
  1307.  
  1308.     /*st_x=x-8;*/
  1309.     if ( opts.play_mode==PM_TETRIS ) {
  1310.         objc_offset(stat,TSTAT0,&st_x,&st_y);
  1311.         y=st_y+stat[TSTAT0].ob_height/2;
  1312.         objc_offset(stat,TSTAT0+1,&w,&h);
  1313.         h+=stat[TSTAT0+1].ob_height/2;
  1314.     }
  1315.     else {
  1316.         objc_offset(stat,CSTAT0,&st_x,&st_y);
  1317.         y=st_y+stat[CSTAT0].ob_height/2;
  1318.         objc_offset(stat,CSTAT0+1,&w,&h);
  1319.         h+=stat[CSTAT0+1].ob_height/2;
  1320.     }
  1321.     st_dy=h-y;
  1322.  
  1323.     wind_update(BEG_UPDATE);
  1324.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  1325.     while ( w!=0 ) {
  1326.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  1327.             xhide(&hide,x,y,w,h);
  1328.             objc_draw(stat,0,MAX_DEPTH,x,y,w,h);
  1329.             xy[0]=x;
  1330.             xy[1]=y;
  1331.             xy[2]=x+w-1;
  1332.             xy[3]=y+h-1;
  1333.             vs_clip(handle,1,xy);
  1334.             game->dr_stat(st_x,st_y,st_dy);
  1335.             vs_clip(handle,0,xy);
  1336.         }
  1337.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1338.     }
  1339.     if ( hide )
  1340.         v_show_c(handle,1);
  1341.     wind_update(END_UPDATE);
  1342. }
  1343.  
  1344. int _stat[10];
  1345.  
  1346. void dr_stat(uint *nstat)
  1347. {
  1348. int x,y,w,h;
  1349. int i,ii,o;
  1350.  
  1351.     if ( opts.play_mode==PM_TETRIS ) {
  1352.         ii=7;
  1353.         o=TSTAT0;
  1354.     }
  1355.     else {
  1356.         ii=6;
  1357.         o=CSTAT0;
  1358.     }
  1359.     for ( i=0; i<ii; i++,o++ ) {
  1360.       int hide=0;
  1361.         if ( nstat[i]!=_stat[i] ) {
  1362.             _stat[i]=nstat[i];
  1363.             sprintf(obj_tedstr(stat,o),"%3d",nstat[i]);
  1364.  
  1365.             if ( stat_flag ) {
  1366.                 wind_get(wind[W_STATISTIC].handle,WF_WORKXYWH,&x,&y,&w,&h);
  1367.                 stat->ob_x=x;
  1368.                 stat->ob_y=y;
  1369.  
  1370.                 wind_update(BEG_UPDATE);
  1371.                 wind_get(wind[W_STATISTIC].handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  1372.                 while ( w ) {
  1373.                     xhide(&hide,x,y,w,h);
  1374.                     objc_draw(stat,o,0,x,y,w,h);
  1375.                     wind_get(wind[W_STATISTIC].handle,WF_NEXTXYWH,&x,&y,&w,&h);
  1376.                 }
  1377.                 if ( hide )
  1378.                     v_show_c(handle,1);
  1379.                 wind_update(END_UPDATE);
  1380.             }
  1381.         }
  1382.     }
  1383. }
  1384.  
  1385. int open_stat(void)
  1386. {
  1387. int x,y,w,h,dummy;
  1388.  
  1389.     wind[W_STATISTIC].handle=wind_create(WIND_ELEMENTS,0,0,screen_w,screen_h);
  1390.     if ( wind[W_STATISTIC].handle<0 )
  1391.         return 0;
  1392.     wind_calc(WC_BORDER,WIND_ELEMENTS,
  1393.         pos[opts.play_mode]->wind_pos[W_STATISTIC].x,pos[opts.play_mode]->wind_pos[W_STATISTIC].y,
  1394.         stat->ob_width,stat->ob_height,&x,&y,&w,&h);
  1395.     check_windpos(&x,&y);
  1396.     wind_set(wind[W_STATISTIC].handle,WF_NAME," Stat. ");
  1397.     wind_open(wind[W_STATISTIC].handle,x,y,w,h);
  1398.     if ( opts.cycle==2 )
  1399.         av_send(AV_ACCWINDOPEN,wind[W_STATISTIC].handle,0,0l,0,0l);
  1400.     wind_get(wind[W_STATISTIC].handle,WF_WORKXYWH,&pos[opts.play_mode]->wind_pos[W_STATISTIC].x,&pos[opts.play_mode]->wind_pos[W_STATISTIC].y,&dummy,&dummy);
  1401.     redraw_statistic(0l);
  1402.     if ( wind[W_PLAY].handle>=0 ) {
  1403.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1404.         redraw_play(0l);
  1405.     }
  1406.     return 1;
  1407. }
  1408.  
  1409. void set_statistic(void)
  1410. {
  1411.     if ( stat_flag ) {
  1412.         wind_close(wind[W_STATISTIC].handle);
  1413.         wind_delete(wind[W_STATISTIC].handle);
  1414.         av_send(AV_ACCWINDCLOSED,wind[W_STATISTIC].handle,0,0l,0,0l);
  1415.         wind[W_STATISTIC].handle=-1;
  1416.     }
  1417.     else {
  1418.         if ( !open_stat() )
  1419.             return;
  1420.     }
  1421.     stat_flag=1-stat_flag;
  1422.     opts.opts[opts.play_mode].statistic=stat_flag;
  1423.     menu_icheck(menue,M_STATISTIC,stat_flag);
  1424. }
  1425.  
  1426.  
  1427. void redraw_icon(int *msg)
  1428. {
  1429.     wind_update(BEG_UPDATE);
  1430.     _redraw_icon(msg[3],msg+4,icon,icon_nr);
  1431.     wind_update(END_UPDATE);
  1432. }
  1433.  
  1434. typedef struct {
  1435.     int x,y,w,h;            /* BORDER */
  1436. } WIND_DATA;
  1437. WIND_DATA iconified_data[4];
  1438.  
  1439. int init_iconify(EVENT *event)    /* event nur bei aes-iconify nötig */
  1440. {
  1441. int x,y,w,h;
  1442. int first;
  1443. WINDOWS wi;
  1444.  
  1445.     if ( !aes_iconify ) {
  1446.         if ( iconified_handle!=-1 )
  1447.             return -1;
  1448.  
  1449.         iconified_pos=(*iconify_server)(ICF_GETPOS,&x,&y,&w,&h);
  1450.         if ( iconified_pos<=0 )
  1451.             return -1;            /* war wohl nix */
  1452.         first=0;
  1453.     }
  1454.     else {
  1455.         wind_get(wind[W_PLAY].handle,WF_CURRXYWH,&iconified_data[W_PLAY].x,&iconified_data[W_PLAY].y,&iconified_data[W_PLAY].w,&iconified_data[W_PLAY].h);
  1456.         my_wind_set(wind[W_PLAY].handle,WF_ICONIFY,event->ev_mmgpbuf[4],event->ev_mmgpbuf[5],event->ev_mmgpbuf[6],event->ev_mmgpbuf[7]);
  1457.         first=1;    /* play-window nicht schließen */
  1458.     }
  1459.  
  1460.     for ( wi=first; wi<WIND_ANZ; wi++ ) {
  1461.         if ( wind[wi].handle>=0 ) {
  1462.             wind_get(wind[wi].handle,WF_CURRXYWH,&iconified_data[wi].x,&iconified_data[wi].y,&iconified_data[wi].w,&iconified_data[wi].h);
  1463.             wind_close(wind[wi].handle);
  1464.             wind_delete(wind[wi].handle);
  1465.             av_send(AV_ACCWINDCLOSED,wind[wi].handle,0,0l,0,0l);
  1466.             wind[wi].handle=-2;
  1467.         }
  1468.     }
  1469.  
  1470.     if ( !aes_iconify ) {
  1471.         iconified_handle=wind_create(NAME|MOVER,x,y,w,h);
  1472.         if ( iconified_handle<0 )
  1473.             return -2;            /* BIG TROUBLE */
  1474.  
  1475.         wind_set(iconified_handle,WF_NAME," WinColTris ");
  1476.         wind_open(iconified_handle,x,y,w,h);
  1477.     }
  1478.  
  1479.     if ( opts.play_mode==PM_COLUMNS ) {
  1480.         icon_nr=ICON_COLUMNS;
  1481.         obj_hide(icon,ICON_TETRIS);
  1482.     }
  1483.     else {
  1484.         icon_nr=ICON_TETRIS;
  1485.         obj_hide(icon,ICON_COLUMNS);
  1486.     }
  1487.     obj_unhide(icon,icon_nr);
  1488.  
  1489.     return 0;
  1490. }
  1491.  
  1492. int is_iconified(void)
  1493. {
  1494. int iconified,dummy;
  1495.  
  1496.     if ( !aes_iconify )
  1497.         return iconified_handle>=0;
  1498.     else {
  1499.         my_wind_get(wind[W_PLAY].handle,WF_ICONIFY,&iconified,&dummy,&dummy,&dummy);
  1500.         return iconified!=0;
  1501.     }
  1502. }
  1503.  
  1504. int exit_iconify(void)
  1505. {
  1506. WINDOWS wi;
  1507. int first;
  1508.  
  1509.     if ( !is_iconified() )
  1510.         return -1;
  1511.  
  1512.     if ( !aes_iconify ) {
  1513.         wind_close(iconified_handle);
  1514.         wind_delete(iconified_handle);
  1515.         (*iconify_server)(ICF_FREEPOS,iconified_pos);
  1516.         iconified_handle=-1;
  1517.         first=0;
  1518.     }
  1519.     else {
  1520.         first=1;
  1521.     }
  1522.     for ( wi=WIND_ANZ-1; wi>=first; wi-- ) {
  1523.         if ( wind[wi].handle==-2 ) {
  1524.             wind[wi].handle=wind_create(WIND_ELEMENTS,0,0,screen_w,screen_h);
  1525.             if ( wind[wi].handle<0 )
  1526.                 return -2;
  1527.             switch ( wi ) {
  1528.               case W_PLAY:
  1529.                 if ( opts.play_mode==PM_COLUMNS )
  1530.                     wind_set(wind[W_PLAY].handle,WF_NAME," Columns ");
  1531.                 else
  1532.                     wind_set(wind[W_PLAY].handle,WF_NAME," Tetris ");
  1533.               break;
  1534.               case W_SCORE:
  1535.                 wind_set(wind[W_SCORE].handle,WF_NAME," Score ");
  1536.               break;
  1537.               case W_PREVIEW:
  1538.                 wind_set(wind[W_PREVIEW].handle,WF_NAME," Preview ");
  1539.               break;
  1540.               case W_STATISTIC:
  1541.                 wind_set(wind[W_STATISTIC].handle,WF_NAME," Stat. ");
  1542.               break;
  1543.             }
  1544.             wind_open(wind[wi].handle,iconified_data[wi].x,iconified_data[wi].y,iconified_data[wi].w,iconified_data[wi].h);
  1545.             if ( (wi==W_PLAY && opts.cycle) || opts.cycle==2 )
  1546.                 av_send(AV_ACCWINDOPEN,wind[wi].handle,0,0l,0,0l);
  1547.         }
  1548.     }
  1549.  
  1550.     if ( aes_iconify )
  1551.         my_wind_set(wind[W_PLAY].handle,WF_UNICONIFY,iconified_data[W_PLAY].x,iconified_data[W_PLAY].y,iconified_data[W_PLAY].w,iconified_data[W_PLAY].h);
  1552.  
  1553.     return 0;
  1554. }
  1555.  
  1556.  
  1557. /*------------------------------------------------------------------------------
  1558.  
  1559.     spiel aufrufen
  1560.  
  1561. ------------------------------------------------------------------------------*/
  1562. void do_play(void)
  1563. {
  1564. int dummy,gret;
  1565. int preview,score,statistic;
  1566. WINDOWS w;
  1567.  
  1568.     menu_tnormal(menue,MT_FILE,1);
  1569.     menu_ienable(menue,M_QUIT,0);
  1570.     menu_ienable(menue,M_ABORT,0);
  1571.     menu_ienable(menue,M_START,0);
  1572.     menu_ienable(menue,M_TETRIS,0);
  1573.     menu_ienable(menue,M_COLUMNS,0);
  1574.      menu_ienable(menue,M_OPTS,0);
  1575.      menu_ienable(menue,M_STONES,0);
  1576.     
  1577.     if ( !opts.multi ) {
  1578.         v_hide_c(handle);
  1579.         wind_update(BEG_MCTRL);
  1580.         wind_update(BEG_UPDATE);
  1581.     }
  1582.     if ( opts.top ) {
  1583.         for ( w=WIND_ANZ-1; w>=0; w-- ) {
  1584.             if ( wind[w].handle>=0 ) {
  1585.                 wind_set(wind[w].handle,WF_TOP);
  1586.                 wind[w].redraw(0l);
  1587.             }
  1588.         }
  1589.     }
  1590.     else {
  1591.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1592.         redraw_play(0l);
  1593.     }
  1594.  
  1595.     preview=preview_flag;
  1596.     score=score_flag;
  1597.     statistic=stat_flag;
  1598.  
  1599.     clr_feld();
  1600.  
  1601.     if ( preview_flag )
  1602.         wind_get(wind[W_PREVIEW].handle,WF_WORKXYWH,&prev_x,&prev_y,&prev_w,&prev_h);
  1603.     wind_get(wind[W_PLAY].handle,WF_WORKXYWH,&x_off,&y_off,&dummy,&dummy);
  1604.  
  1605.     init_copy_out();
  1606.  
  1607.     in_game=1;
  1608. #if SOUND_LEVEL>0
  1609.     do_sound(S_START);
  1610. #endif
  1611.  
  1612.     gret=game->play();
  1613.  
  1614. #if SOUND_LEVEL>0
  1615.     do_sound(S_GAMEOVER);
  1616. #endif
  1617.     in_game=0;
  1618.  
  1619.     if ( !gret ) {    /* spielabbruch -> loesche spielfeld */
  1620.         clr_feld();
  1621. #if SOUND_LEVEL>0
  1622.     do_sound(S_ABORT);
  1623. #endif
  1624.     }
  1625.     else {
  1626.         do_score(gret,opts.hiscore[opts.play_mode]);
  1627.         do_endgame();
  1628.     }
  1629.     if ( preview!=preview_flag )
  1630.         set_preview();
  1631.     else if ( preview_flag )
  1632.         redraw_preview(0l);
  1633.     if ( score!=score_flag )
  1634.         set_score();
  1635.     if ( statistic!=stat_flag )
  1636.         set_statistic();
  1637.  
  1638.     menu_ienable(menue,M_QUIT,1);
  1639.     menu_ienable(menue,M_ABORT,1);
  1640.     menu_ienable(menue,M_START,1);
  1641.     if ( tetris.vdi!=-1 )
  1642.         menu_ienable(menue,M_TETRIS,1);
  1643.     if ( columns.vdi!=-1 )
  1644.         menu_ienable(menue,M_COLUMNS,1);
  1645.     menu_ienable(menue,M_OPTS,1);
  1646.     menu_ienable(menue,M_STONES,1);
  1647.  
  1648.     if ( !opts.multi ) {
  1649.         wind_update(END_MCTRL);
  1650.         wind_update(END_UPDATE);
  1651.         v_show_c(handle,1);
  1652.     }
  1653. }
  1654.  
  1655. /*------------------------------------------------------------------------------
  1656.  
  1657.     programm-info ausgeben
  1658.  
  1659. ------------------------------------------------------------------------------*/
  1660. void prog_info(void)
  1661. {
  1662. int x,y,w,h,r;
  1663.  
  1664.     form_center(info,&x,&y,&w,&h);
  1665.     wind_update(BEG_UPDATE);
  1666.     form_dial(FMD_START,x,y,w,h,x,y,w,h);
  1667.     objc_draw(info,0,10,x,y,w,h);
  1668.     r=form_do(info,0)&0x7FFF;
  1669.     form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  1670.     wind_update(END_UPDATE);
  1671.     obj_unselect(info,r);
  1672. }
  1673.  
  1674. /*------------------------------------------------------------------------------
  1675.  
  1676.     menu-handler
  1677.  
  1678. ------------------------------------------------------------------------------*/
  1679. int do_menue(int titel,int entry)
  1680. {
  1681. int ret=0;
  1682.  
  1683.     if ( obj_state(menue,entry)&DISABLED )
  1684.         return 0;
  1685.  
  1686.     if ( is_iconified() && entry!=M_QUIT && entry!=M_ABORT && entry!=M_INFO && entry!=M_OPTS && entry!=M_HISCORE && entry!=M_SCORE ) {
  1687.         if ( exit_iconify()<-1 )
  1688.             return -1;
  1689.     }
  1690.     
  1691.     switch ( entry ) {
  1692.       case M_INFO:        prog_info();        break;
  1693.       case M_START:        do_play();            break;
  1694.       case M_HISCORE:    show_hiscore();        break;
  1695.       case M_QUIT:        save_options();ret=1;break;
  1696.       case M_ABORT:        ret=2;                break;
  1697.       case M_TETRIS:    set_playmode(PM_TETRIS);break;
  1698.       case M_COLUMNS:    set_playmode(PM_COLUMNS);break;
  1699.       case M_SCORE:        set_score();        break;
  1700.       case M_PREVIEW:    set_preview();        break;
  1701.       case M_STATISTIC:    set_statistic();    break;
  1702.       case M_OPTS:        do_options();        break;
  1703.       case M_STONES:    change_stones();    break;
  1704.     }
  1705.     if ( titel )
  1706.         menu_tnormal(menue,titel,1);
  1707.     return ret;
  1708. }
  1709.  
  1710. /*------------------------------------------------------------------------------
  1711.  
  1712.     event-schleife
  1713.  
  1714. ------------------------------------------------------------------------------*/
  1715. WINDOWS get_window(int handle)
  1716. {
  1717. WINDOWS w;
  1718.  
  1719.     for ( w=0; w<WIND_ANZ; w++ )
  1720.         if ( handle==wind[w].handle )
  1721.             return w;
  1722.     return -1;                                    /* hmm, should not happen */
  1723. }
  1724.  
  1725. int do_control(int flag)
  1726. {
  1727. int dummy;
  1728. WINDOWS w;
  1729. EVENT event;
  1730. int evnt,i;
  1731. int key,ret;
  1732.  
  1733.     if ( flag<=0 ) {
  1734.         event.ev_mflags=MU_MESAG|MU_KEYBD;
  1735.     }
  1736.     else if ( flag>0 ) {
  1737.         event.ev_mflags=MU_MESAG|MU_TIMER;
  1738.         event.ev_mtlocount=flag;
  1739.         event.ev_mthicount=0;
  1740.     }
  1741.     while ( 1 ) {
  1742.         if ( iconified_handle>=0 ) {
  1743.             event.ev_mflags|=MU_BUTTON;
  1744.             event.ev_mbclicks=event.ev_bmask=event.ev_mbstate=1;
  1745.         }
  1746.         else {
  1747.             event.ev_mflags&=~MU_BUTTON;
  1748.         }
  1749.         evnt=EvntMulti(&event);
  1750.  
  1751.         if ( evnt==MU_TIMER )
  1752.             return 0;
  1753.         if ( evnt&MU_BUTTON ) {
  1754.             if ( wind_find(event.ev_mmox,event.ev_mmoy)==iconified_handle )
  1755.                 if ( exit_iconify()<-1 )
  1756.                     return 1;
  1757.         }
  1758.         if ( evnt&MU_KEYBD ) {
  1759.             if ( flag<0 )
  1760.                 return 0;
  1761.  
  1762.             key=*(char*)&event.ev_mkreturn;
  1763.             event.ev_mmokstate&=~(K_LSHIFT|K_RSHIFT);
  1764.             for ( i=0; i<(int)(sizeof(commands)/sizeof(commands[0])); i++ ) {
  1765.                 if ( key==commands[i].key && event.ev_mmokstate==commands[i].state ) {
  1766.                     ret=do_menue(0,commands[i].entry);
  1767.                     if ( ret==-1 )
  1768.                         return 1;
  1769.                     else if ( ret )
  1770.                         return 0;
  1771.                     break;
  1772.                 }
  1773.             }
  1774.             if ( i==(int)(sizeof(commands)/sizeof(commands[0])) )
  1775.                 av_send(AV_SENDKEY,event.ev_mmokstate,event.ev_mkreturn,0l,0,0l);
  1776.         }
  1777.         else if ( evnt&MU_MESAG ) {
  1778.             switch ( event.ev_mmgpbuf[0] ) {
  1779.               case MN_SELECTED:
  1780.                   ret=do_menue(event.ev_mmgpbuf[3],event.ev_mmgpbuf[4]);
  1781.                 if ( ret==-1 )
  1782.                     return 1;
  1783.                 else if ( ret )
  1784.                     return 0;
  1785.               break;
  1786.               case WM_REDRAW:
  1787.                   w=get_window(event.ev_mmgpbuf[3]);
  1788.                   if ( w!=W_ERROR )
  1789.                     wind[w].redraw(event.ev_mmgpbuf);
  1790.                 else if ( event.ev_mmgpbuf[3]==iconified_handle )
  1791.                     redraw_icon(event.ev_mmgpbuf);
  1792.               break;
  1793.               case WM_TOPPED:
  1794.                   wind_set(event.ev_mmgpbuf[3],WF_TOP);
  1795.               break;
  1796.               case WM_MOVED:
  1797.                 w=get_window(event.ev_mmgpbuf[3]);
  1798.                 if ( w==W_PLAY && !is_iconified() ) {
  1799.                   int x,y,w,h;
  1800.                       wind_calc(WC_WORK,WIND_ELEMENTS,event.ev_mmgpbuf[4],event.ev_mmgpbuf[5],event.ev_mmgpbuf[6],event.ev_mmgpbuf[7],&x,&y,&w,&h);
  1801.                       x&=~15;
  1802.                       wind_calc(WC_BORDER,WIND_ELEMENTS,x,y,w,h,event.ev_mmgpbuf+4,event.ev_mmgpbuf+5,event.ev_mmgpbuf+6,event.ev_mmgpbuf+7);
  1803.                 }
  1804.                 wind_set(event.ev_mmgpbuf[3],WF_CURRXYWH,event.ev_mmgpbuf[4],event.ev_mmgpbuf[5],event.ev_mmgpbuf[6],event.ev_mmgpbuf[7]);
  1805.                 if ( w!=W_ERROR ) {
  1806.                     if ( !(w==W_PLAY && is_iconified()) )
  1807.                         wind_get(event.ev_mmgpbuf[3],WF_WORKXYWH,&pos[opts.play_mode]->wind_pos[w].x,&pos[opts.play_mode]->wind_pos[w].y,&dummy,&dummy);
  1808.                     if ( w==W_PREVIEW )
  1809.                         wind_get(wind[W_PREVIEW].handle,WF_WORKXYWH,&prev_x,&prev_y,&prev_w,&prev_h);
  1810.                     if ( w==W_PLAY && !is_iconified() )
  1811.                         wind_get(wind[W_PLAY].handle,WF_WORKXYWH,&x_off,&y_off,&dummy,&dummy);
  1812.                 }
  1813.               break;
  1814.               case WM_ICONIFY:
  1815.               case WM_ALLICONIFY:
  1816.                 init_iconify(&event);
  1817.               break;
  1818.               case WM_UNICONIFY:
  1819.                   exit_iconify();
  1820.               break;
  1821.               case WM_CLOSED:
  1822.                 w=get_window(event.ev_mmgpbuf[3]);
  1823.                 if ( w!=W_ERROR ) {
  1824.                     if ( iconify_server!=0l && event.ev_mmokstate&(K_ALT|K_LSHIFT|K_RSHIFT|K_CTRL) ) {
  1825.                         if ( flag>0 )
  1826.                             break;
  1827.                         if ( init_iconify(0l)<-1 )
  1828.                             return 1;
  1829.                     }
  1830.                     else if ( !(flag && w==W_PLAY) ) {
  1831.                           if ( w==W_PLAY )
  1832.                               return 0;
  1833.                           wind[w].close();
  1834.                     }
  1835.                 }
  1836.               break;
  1837.             }
  1838.         }
  1839.     }
  1840. }
  1841.  
  1842.  
  1843. /*------------------------------------------------------------------------------
  1844.  
  1845.     initialisierung
  1846.  
  1847. ------------------------------------------------------------------------------*/
  1848. typedef struct
  1849. {
  1850.     long id;
  1851.     long value;
  1852. } COOKJAR;
  1853.  
  1854. static long _get_cookjar(void)
  1855. {
  1856.     return *(long*)0x05a0l;
  1857. }
  1858.  
  1859. long get_cookie(long cookie)
  1860. {
  1861. COOKJAR    *cookiejar;
  1862. int    i = 0;
  1863.  
  1864.     cookiejar=(COOKJAR*)Supexec(_get_cookjar);
  1865.  
  1866.     if ( cookiejar ) {
  1867.         while ( cookiejar[i].id ) {
  1868.             if ( cookiejar[i].id==cookie )
  1869.                 return cookiejar[i].value;
  1870.             i++;
  1871.         }
  1872.     }
  1873.     return 0l;
  1874. }
  1875.  
  1876. OBJECT *scale_tree(int index)
  1877. {
  1878. OBJECT *tree;
  1879.  
  1880.     tree=rs_trindex[index];
  1881.     do {
  1882.         rsrc_obfix(tree,0);
  1883.     } while ( !(tree++->ob_flags&LASTOB) );
  1884.     return rs_trindex[index];
  1885. }
  1886.  
  1887. void init_pos(void)
  1888. {
  1889. int i,j;
  1890. int width,height;
  1891. int desk_x,desk_y,desk_w,desk_h;
  1892. long h;
  1893. WINDOWS w;
  1894.  
  1895.  
  1896.     wind_get(0,WF_WORKXYWH,&desk_x,&desk_y,&desk_w,&desk_h);
  1897.  
  1898.     for ( j=0; j<2; j++ ) {
  1899.         if ( j==PM_TETRIS ) {
  1900.             width=tetris.block_w*tetris.game_width;
  1901.             height=tetris.block_h*tetris.game_height;
  1902.         }
  1903.         else {
  1904.             width=columns.block_w*columns.game_width;
  1905.             height=columns.block_h*columns.game_height;
  1906.         }
  1907.  
  1908.         for ( i=0; i<POSITIONS; i++ ) {
  1909.             pos[j]=&opts.pos[j][i];
  1910.             if ( pos[j]->desk_x==desk_x && pos[j]->desk_y==desk_y && pos[j]->desk_w==desk_w && pos[j]->desk_h==desk_h && pos[j]->width==width && pos[j]->height==height )
  1911.                 break;
  1912.         }
  1913.         if ( i==POSITIONS ) {
  1914.             for ( i=POSITIONS-1; i>0; i-- )
  1915.                 opts.pos[j][i]=opts.pos[j][i-1];
  1916.             pos[j]=&opts.pos[j][0];
  1917.             for ( w=0; w<WIND_ANZ; w++ ) {
  1918.                 h=(long)(pos[j]->wind_pos[w].x-pos[j]->desk_x)*desk_w;
  1919.                 pos[j]->wind_pos[w].x=(int)(h/pos[j]->desk_w)+desk_x;
  1920.                 h=(long)(pos[j]->wind_pos[w].y-pos[j]->desk_y)*desk_h;
  1921.                 pos[j]->wind_pos[w].y=(int)(h/pos[j]->desk_h)+desk_y;
  1922.             }
  1923.             pos[j]->desk_x=desk_x;
  1924.             pos[j]->desk_y=desk_y;
  1925.             pos[j]->desk_w=desk_w;
  1926.             pos[j]->desk_h=desk_h;
  1927.             pos[j]->width=width;
  1928.             pos[j]->height=height;
  1929.         }
  1930.     }
  1931. }
  1932.  
  1933. int do_init(void)
  1934. {
  1935. int i,f_id;
  1936. int p_handle,dummy,work_in[11],work_out[57];
  1937.  
  1938.     ap_id=appl_init();
  1939.  
  1940.     if ( _GemParBlk.global[0]>=0x400 || !appl_find("?AGI") ) {
  1941.       int o1,o2,o3,o4;
  1942.         appl_getinfo(11,&o1,&o2,&o3,&o4);
  1943.         if ( (o1&0x0180)==0x0180 )
  1944.             aes_iconify=1;
  1945.     }
  1946.     av_init();
  1947.  
  1948.     if ( !aes_iconify )
  1949.         iconify_server=(void*)get_cookie('ICFS');
  1950.  
  1951.         /* init resources */
  1952.     menue    =    scale_tree(MENUE);
  1953.     score    =    scale_tree(XSCORE);
  1954.     stat    =    scale_tree(STATISTIC);
  1955.     options    =    scale_tree(OPTSBOX);
  1956.     info    =    scale_tree(INFOBOX);
  1957.     user_keys=    scale_tree(KEYS);
  1958.     hiscore    =    scale_tree(HISCORE);
  1959.     hi_name    =    scale_tree(NEWHI);
  1960.     icon    =    scale_tree(ICON);
  1961.  
  1962.     obj_spec(info,I_COMPDATE)=__DATE__;
  1963.     *obj_tedstr(hi_name,HI_NAME)=0;
  1964.  
  1965.         /* lese voreinstellung */
  1966.       set_file[0]=Dgetdrv()+'A';
  1967.       set_file[1]=':';
  1968.       Dgetpath(set_file+2,0);
  1969.     strcat(set_file,"\\COLTRIS.SET");
  1970.     f_id=Fopen(set_file,0);
  1971.     if ( f_id>0 ) {
  1972.         Fread(f_id,sizeof(opts),&opts);
  1973.         Fclose(f_id);
  1974.     }
  1975.  
  1976.  
  1977.         /* init vdi */
  1978.     p_handle=graf_handle(&dummy,&dummy,&dummy,&dummy);
  1979.     for ( i=0; i<10; i++ )
  1980.         work_in[i]=1;
  1981.     work_in[10]=2;
  1982.     handle=p_handle;
  1983.     v_opnvwk(work_in,&handle,work_out);
  1984.     graf_mouse(0,0);
  1985.  
  1986.     screen_w=work_out[0]+1;
  1987.     screen_h=work_out[1]+1;
  1988.  
  1989.     vq_extnd(handle,1,work_out);
  1990.     planes=work_out[4];
  1991.     if ( planes==1 )
  1992.         planes_nr=0;
  1993.     else if ( planes==2 )
  1994.         planes_nr=1;
  1995.     else if ( planes==4 )
  1996.         planes_nr=2;
  1997.     else if ( planes==8 )
  1998.         planes_nr=3;
  1999.     else                    /* hmm, big trouble... */
  2000.         return 0;
  2001.  
  2002.     vswr_mode(handle,MD_REPLACE);
  2003.     vsf_interior(handle,FIS_PATTERN);
  2004.     vsf_perimeter(handle,0);
  2005.  
  2006.     vst_color(handle,0);
  2007.     vst_height(handle,20,&dummy,&dummy,&dummy,&dummy);
  2008.     /*vst_effects(handle,16);*/
  2009.     vst_alignment(handle,1,1,&dummy,&dummy);
  2010.  
  2011.     av_getproto();
  2012.  
  2013.     return 1;
  2014. }
  2015.  
  2016. void do_exit(int ret)
  2017. {
  2018. WINDOWS w;
  2019.  
  2020.     wind_update(BEG_UPDATE);
  2021.     if ( ret==1 )
  2022.         form_error(8);
  2023.     else if ( ret==2 )
  2024.         form_alert(1,"[1][ | Missing or incorrect | | Image-Files! | ][ Exit ]");
  2025.     else if ( ret==3 )
  2026.         form_alert(1,"[1][ | Unable to open window! | ][ Exit ]");
  2027.     else if ( ret==4 )
  2028.         form_alert(1,"[1][ | Unsupported resolution! | ][ Exit ]");
  2029.     else if ( ret!=0 )
  2030.         form_alert(1,"[1][ | Something went wrong! | ][ Exit ]");
  2031.     wind_update(END_UPDATE);
  2032.  
  2033.     for ( w=0; w<WIND_ANZ; w++ ) {
  2034.         if ( wind[w].handle>=0 ) {
  2035.             wind_close(wind[w].handle);
  2036.             wind_delete(wind[w].handle);
  2037.             av_send(AV_ACCWINDCLOSED,wind[w].handle,0,0l,0,0l);
  2038.         }
  2039.     }
  2040.     if ( iconified_handle>=0 ) {
  2041.         wind_close(iconified_handle);
  2042.         wind_delete(iconified_handle);
  2043.         (*iconify_server)(ICF_FREEPOS,iconified_pos);
  2044.     }
  2045.  
  2046.     v_clsvwk(handle);
  2047.     av_send(AV_EXIT,0,0,0l,0,0l);
  2048.     appl_exit();
  2049.     if ( buffer_addr )
  2050.         free((void*)buffer_addr);
  2051.  
  2052.     exit(ret);
  2053. }
  2054.  
  2055. void main(int argc,char *argv[])
  2056. {
  2057. int ret;
  2058.  
  2059.     if ( !do_init() )
  2060.         do_exit(4);
  2061.  
  2062. #if SOUND_LEVEL>0
  2063.     init_sound(argc,argv);
  2064. #endif
  2065.  
  2066.     if ( !init_image(&columns,opts.stone_file[PM_COLUMNS][planes_nr],argc,argv) )
  2067.         if ( !init_image(&columns,"COLUMNS1.IMG",0,0l) )
  2068.             menu_ienable(menue,M_COLUMNS,0);
  2069.     if ( !init_image(&tetris,opts.stone_file[PM_TETRIS][planes_nr],argc,argv) )
  2070.         if ( !init_image(&columns,"TETRIS1.IMG",0,0l) )
  2071.             menu_ienable(menue,M_TETRIS,0);
  2072.  
  2073.     if ( obj_state(menue,M_COLUMNS)&DISABLED && obj_state(menue,M_TETRIS)&DISABLED )
  2074.         do_exit(2);
  2075.  
  2076.     if ( opts.play_mode==PM_COLUMNS && !(obj_state(menue,M_COLUMNS)&DISABLED) ) {
  2077.         menu_icheck(menue,M_COLUMNS,1);
  2078.         obj_unhide(stat,C_STAT);
  2079.         obj_hide(stat,TSTAT);
  2080.         game=&columns;
  2081.     }
  2082.     else {
  2083.         menu_icheck(menue,M_TETRIS,1);
  2084.         obj_hide(stat,C_STAT);
  2085.         obj_unhide(stat,TSTAT);
  2086.         opts.play_mode=PM_TETRIS;
  2087.         game=&tetris;
  2088.     }
  2089.  
  2090.     init_pos();
  2091.  
  2092.     menu_bar(menue,1);
  2093.  
  2094.     if ( opts.opts[opts.play_mode].score )
  2095.         set_score();
  2096.     if ( opts.opts[opts.play_mode].preview )
  2097.         set_preview();
  2098.     if ( opts.opts[opts.play_mode].statistic )
  2099.         set_statistic();
  2100.     if ( !open_window() )
  2101.         do_exit(3);
  2102.  
  2103.     do {
  2104.         ret=do_control(0);
  2105.         if ( !ret ) {
  2106.             if ( opts.alert ) {
  2107.                 wind_update(BEG_UPDATE);
  2108.                 ret=form_alert(2,"[0][ |       See you...       | ][ Cancel |Ok]")!=1;
  2109.                 wind_update(END_UPDATE);
  2110.             }
  2111.             else
  2112.                 ret=1;
  2113.         }
  2114.         else {
  2115.             wind_update(BEG_UPDATE);
  2116.             form_alert(1,"[0][ | Something went wrong... | | See you... | ][ Cancel ]");
  2117.             wind_update(END_UPDATE);
  2118.         }
  2119.     } while ( !ret  );
  2120.  
  2121.     do_exit(0);
  2122. }
  2123.